<script>

  function createStore(reducer, initState, rewriteCreateStoreFunc) {
    if (typeof initState === 'function'){
      rewriteCreateStoreFunc = initState;
      initState = undefined;
    }
    /*如果有 rewriteCreateStoreFunc，那就采用新的 createStore */
    if(rewriteCreateStoreFunc){
       const newCreateStore =  rewriteCreateStoreFunc(createStore);
       return newCreateStore(reducer, initState);
    }
    let state = initState;
    let listeners = [];

    function subscribe(listener) {
      listeners.push(listener);
      return function unsubscribe() {
        const index = listeners.indexOf(listener)
        listeners.splice(index, 1)
      }
    }

    function dispatch(action) {
      state = reducer(state, action);
      for (let i = 0; i < listeners.length; i++) {
        const listener = listeners[i];
        listener();
      }
    }

    function getState() {
      return state;
    }
    /* 注意！！！只修改了这里，用一个不匹配任何计划的 type，来获取初始值 */
    dispatch({ type: Symbol() })

    return {
      subscribe,
      dispatch,
      getState
    }
  }

  function combineReducers(reducers) {

    /* reducerKeys = ['counter', 'info']*/
    const reducerKeys = Object.keys(reducers)

    /*返回合并后的新的reducer函数*/
    return function combination(state = {}, action) {
      /*生成的新的state*/
      const nextState = {}

      /*遍历执行所有的reducers，整合成为一个新的state*/
      for (let i = 0; i < reducerKeys.length; i++) {
        const key = reducerKeys[i]
        const reducer = reducers[key]
        /*之前的 key 的 state*/
        const previousStateForKey = state[key]
        /*执行 分 reducer，获得新的state*/
        const nextStateForKey = reducer(previousStateForKey, action)

        nextState[key] = nextStateForKey
      }
      return nextState;
    }
  }

  function applyMiddleware(...middlewares) {
    /*返回一个重写createStore的方法*/
    return function rewriteCreateStoreFunc(oldCreateStore) {
      /*返回重写后新的 createStore*/
      return function newCreateStore(reducer, initState) {
        /*1. 生成store*/
        const store = oldCreateStore(reducer, initState);
        /*给每个 middleware 传下store，相当于 const logger = loggerMiddleware(store);*/
        /* const chain = [exception, time, logger]*/
        const simpleStore = { getState: store.getState };
        const chain = middlewares.map(middleware => middleware(simpleStore));
        dispatch = compose(...chain)(store.dispatch);

        /*2. 重写 dispatch*/
        store.dispatch = dispatch;
        return store;
      }
    }
  }

  function compose(...funcs) {
    if (funcs.length === 1) {
      return funcs[0]
    }
    return funcs.reduce((a, b) => (...args) => a(b(...args)))
  }

</script>